﻿Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Xml.Serialization

Namespace roncliProductions.LibWowArmory

    ''' <summary>
    ''' A class to search items on the Armory with
    ''' </summary>
    ''' <remarks></remarks>
    Public Class ItemSearch
        Inherits WowArmoryXML

#Region "Declarations"

        Private issPage As New ItemSearchSchema.page
        Private qfFilter As New QueryFilter

#End Region

#Region "Properties"

        ''' <summary>
        ''' The current filter to query against
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Filter() As QueryFilter
            Get
                Return qfFilter
            End Get
            Set(ByVal value As QueryFilter)
                qfFilter = value
            End Set
        End Property

        ''' <summary>
        ''' The URL that will be used to search items on the Armory with
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL() As String
            Get
                Dim ubURL As New URLBuilder("http://www.wowarmory.com/search.xml")

                ubURL.Add("searchType", "items")

                'Search query
                If Not String.IsNullOrEmpty(qfFilter.strSearchQuery) Then
                    ubURL.Add("searchQuery", qfFilter.strSearchQuery)
                End If

                'Source filters
                If Not String.IsNullOrEmpty(qfFilter.Source.strSource) Then
                    ubURL.Add("fl[source]", qfFilter.Source.strSource)
                End If
                If Not String.IsNullOrEmpty(qfFilter.Source.strDungeon) Then
                    ubURL.Add("fl[dungeon]", qfFilter.Source.strDungeon)
                End If
                If qfFilter.Source.intBoss <> 0 Then
                    ubURL.Add("fl[boss]", qfFilter.Source.intBoss.ToString())
                End If
                If Not String.IsNullOrEmpty(qfFilter.Source.strDifficulty) Then
                    ubURL.Add("fl[difficulty]", qfFilter.Source.strDifficulty)
                End If
                If Not String.IsNullOrEmpty(qfFilter.Source.strFaction) Then
                    ubURL.Add("fl[faction]", qfFilter.Source.strFaction)
                End If
                If Not String.IsNullOrEmpty(qfFilter.Source.strPvp) Then
                    ubURL.Add("fl[pvp]", qfFilter.Source.strPvp)
                End If

                'Item Type filters
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strItemType) Then
                    ubURL.Add("fl[type]", qfFilter.ItemType.strItemType)
                End If
                If qfFilter.ItemType.intDesiredBy <> 0 Then
                    ubURL.Add("fl[usbleBy]", qfFilter.ItemType.intDesiredBy.ToString())
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strDesiredByRole) Then
                    ubURL.Add("fl[classType]", qfFilter.ItemType.strDesiredByRole)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strRarity) Then
                    ubURL.Add("fl[rrt]", qfFilter.ItemType.strRarity)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strWeaponSlot) Then
                    ubURL.Add("fl[slot]", qfFilter.ItemType.strWeaponSlot)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strWeaponType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strWeaponType)
                End If
                If qfFilter.ItemType.intRequiredLevelMin <> 0 Then
                    ubURL.Add("fl[rqrMin]", qfFilter.ItemType.intRequiredLevelMin.ToString())
                End If
                If qfFilter.ItemType.intRequiredLevelMax <> 0 Then
                    ubURL.Add("fl[rqrMax]", qfFilter.ItemType.intRequiredLevelMax.ToString())
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strArmorSlot) Then
                    ubURL.Add("fl[slot]", qfFilter.ItemType.strArmorSlot)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strArmorType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strArmorType)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strGemType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strGemType)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strBagType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strBagType)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strProjectilesType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strProjectilesType)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strQuiversType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strQuiversType)
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strRecipesType) Then
                    ubURL.Add("fl[subTp]", qfFilter.ItemType.strRecipesType)
                End If
                If qfFilter.ItemType.intSkillLevelMin <> 0 Then
                    ubURL.Add("fl[minSkill]", qfFilter.ItemType.intSkillLevelMin.ToString())
                End If
                If qfFilter.ItemType.intSkillLevelMax <> 0 Then
                    ubURL.Add("fl[maxSkill]", qfFilter.ItemType.intSkillLevelMax.ToString())
                End If
                If Not String.IsNullOrEmpty(qfFilter.ItemType.strPermanentEnchantmentSlot) Then
                    ubURL.Add("fl[slot]", qfFilter.ItemType.strPermanentEnchantmentSlot)
                End If

                For Each aoOption As QueryFilter.AdvancedOptionsFilter In qfFilter.AdvancedOptions
                    If aoOption.AdvancedOptions < AdvancedOptionsType.General_BindOnPickup Then
                        ubURL.Add("fl[advOpt]", String.Format("{0}_{1}_{2}", aoOption.strAdvancedOptions, aoOption.strOperator, aoOption.intRange.ToString()))
                    Else
                        ubURL.Add("fl[advOpt]", aoOption.strAdvancedOptions)
                    End If
                Next

                Return ubURL.ToString()
            End Get
        End Property

        ''' <summary>
        ''' Returns a list of searched items
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Items() As List(Of Item)
            Get
                If IsNothing(issPage) Then
                    Return New List(Of Item)
                End If
                If IsNothing(issPage.armorySearch(0).searchResults(0).items(0).item) Then
                    Return New List(Of Item)
                End If
                Return (From a In issPage.armorySearch(0).searchResults(0).items(0).item Select New Item(a.icon, a.id, a.name, CType(a.rarity, RarityType), a.url, Integer.Parse(a.filter.Where(Function(f) f.name = "relevance").First().value))).ToList()
            End Get
        End Property

#End Region

#Region "Methods"

        ''' <summary>
        ''' Performs the search on the armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Search()
            MyBase.Retrieve()

            Dim xsSerializer As New XmlSerializer(issPage.GetType())

            Dim srXML As New StringReader(MyBase.strXML)

            issPage = CType(xsSerializer.Deserialize(srXML), ItemSearchSchema.page)
        End Sub

#End Region

#Region "Nested Classes"

        ''' <summary>
        ''' A class that encapsulates a single item returned by the Armory search
        ''' </summary>
        ''' <remarks></remarks>
        Public Class Item

            Private strIcon As String
            Private intID As Integer
            Private strName As String
            Private rRarity As RarityType
            Private strURL As String
            Private intRelevance As Integer

            ''' <summary>
            ''' The filename of the item's icon
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Icon() As String
                Get
                    Return strIcon
                End Get
                Set(ByVal value As String)
                    strIcon = value
                End Set
            End Property

            ''' <summary>
            ''' The item's identification number
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property ID() As Integer
                Get
                    Return intID
                End Get
                Set(ByVal value As Integer)
                    intID = value
                End Set
            End Property

            ''' <summary>
            ''' The name of the item
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Name() As String
                Get
                    Return strName
                End Get
                Set(ByVal value As String)
                    strName = value
                End Set
            End Property

            ''' <summary>
            ''' The rarity of the item
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Rarity() As RarityType
                Get
                    Return rRarity
                End Get
                Set(ByVal value As RarityType)
                    rRarity = value
                End Set
            End Property

            ''' <summary>
            ''' The querystring of the item
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property URL() As String
                Get
                    Return strURL
                End Get
                Set(ByVal value As String)
                    strURL = value
                End Set
            End Property

            ''' <summary>
            ''' The relevance of the result
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Relevance() As Integer
                Get
                    Return intRelevance
                End Get
                Set(ByVal value As Integer)
                    intRelevance = value
                End Set
            End Property

            ''' <summary>
            ''' Constructor to create a new item object
            ''' </summary>
            ''' <param name="strIcon"></param>
            ''' <param name="intID"></param>
            ''' <param name="strName"></param>
            ''' <param name="rRarity"></param>
            ''' <param name="strURL"></param>
            ''' <remarks></remarks>
            Friend Sub New(ByVal strIcon As String, ByVal intID As Integer, ByVal strName As String, ByVal rRarity As RarityType, ByVal strURL As String, ByVal intRelevance As Integer)
                Me.strIcon = strIcon
                Me.intID = intID
                Me.strName = strName
                Me.rRarity = rRarity
                Me.strURL = strURL
                Me.intRelevance = intRelevance
            End Sub

            ''' <summary>
            ''' Method to return the extended information from an item
            ''' </summary>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Function ItemInfo() As ItemInfo
                Return New ItemInfo(intID)
            End Function

        End Class

        ''' <summary>
        ''' A class that encapsulates an Armory filter
        ''' </summary>
        ''' <remarks></remarks>
        Public Class QueryFilter

            Friend strSearchQuery As String
            Private sfSource As New SourceFilter
            Private itfItemType As New ItemTypeFilter
            Private lstAdvancedOptions As New List(Of AdvancedOptionsFilter)

            ''' <summary>
            ''' The terms to search item names on the Armory with
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property SearchQuery() As String
                Get
                    Return strSearchQuery
                End Get
                Set(ByVal value As String)
                    strSearchQuery = value
                End Set
            End Property

            ''' <summary>
            ''' The current source filter to query with
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Source() As SourceFilter
                Get
                    Return sfSource
                End Get
                Set(ByVal value As SourceFilter)
                    sfSource = value
                End Set
            End Property

            ''' <summary>
            ''' The current item type filter to query with
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property ItemType() As ItemTypeFilter
                Get
                    Return itfItemType
                End Get
                Set(ByVal value As ItemTypeFilter)
                    itfItemType = value
                End Set
            End Property

            ''' <summary>
            ''' Advanced options to query with
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property AdvancedOptions() As List(Of AdvancedOptionsFilter)
                Get
                    Return lstAdvancedOptions
                End Get
                Set(ByVal value As List(Of AdvancedOptionsFilter))
                    lstAdvancedOptions = value
                End Set
            End Property

            ''' <summary>
            ''' A class that encapsulates the Armory's source filters
            ''' </summary>
            ''' <remarks></remarks>
            Public Class SourceFilter

                Friend strSource As String = "all"
                Friend strDungeon As String
                Friend intBoss As Integer
                Friend strDifficulty As String
                Friend strFaction As String
                Friend strPvp As String

                ''' <summary>
                ''' The source of the items to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Source() As SourceType
                    Get
                        Select Case strSource
                            Case "dungeon"
                                Return SourceType.DungeonsAndRaidDrops
                            Case "reputation"
                                Return SourceType.ReputationRewards
                            Case "quest"
                                Return SourceType.QuestRewards
                            Case "pvpAlliance"
                                Return SourceType.PvpRewardsAlliance
                            Case "pvpHorde"
                                Return SourceType.PvpRewardsHorde
                            Case Else
                                Return SourceType.AllSources
                        End Select
                    End Get
                    Set(ByVal value As SourceType)
                        Clear()
                        Select Case value
                            Case SourceType.AllSources
                                strSource = "all"
                            Case SourceType.DungeonsAndRaidDrops
                                strSource = "dungeon"
                                strDungeon = "all"
                            Case SourceType.ReputationRewards
                                strSource = "reputation"
                                strFaction = "-1"
                            Case SourceType.QuestRewards
                                strSource = "quest"
                            Case SourceType.PvpRewardsAlliance
                                strSource = "pvpAlliance"
                                strPvp = "all"
                            Case SourceType.PvpRewardsHorde
                                strSource = "pvpHorde"
                                strPvp = "all"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The dungeon to search for items in
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Dungeon() As Integer
                    Get
                        If strSource = "dungeon" And IsNumeric(strDungeon) Then
                            Return Integer.Parse(strDungeon)
                        Else
                            Return 0
                        End If
                    End Get
                    Set(ByVal value As Integer)
                        Clear()
                        strSource = "dungeon"
                        If value = 0 Then
                            strDungeon = "all"
                        Else
                            strDungeon = value.ToString()
                        End If
                        strDifficulty = "all"
                    End Set
                End Property

                ''' <summary>
                ''' The type of dungeon to search for items in
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property DungeonType() As DungeonType
                    Get
                        If strSource = "dungeon" Then
                            Select Case strDungeon
                                Case "dungeons"
                                    Return DungeonType.DungeonsOnly
                                Case "raids"
                                    Return DungeonType.RaidsOnly
                                Case "badgeofjustice"
                                    Return DungeonType.BadgeOfJusticeRewards
                                Case "emblemofheroism"
                                    Return DungeonType.EmblemOfHeroism
                                Case "emblemofvalor"
                                    Return DungeonType.EmblemOfValor
                                Case Else
                                    Return DungeonType.AllDungeonsAndRaids
                            End Select
                        Else
                            Return DungeonType.AllDungeonsAndRaids
                        End If
                    End Get
                    Set(ByVal value As DungeonType)
                        Clear()
                        strSource = "dungeon"
                        Select Case value
                            Case DungeonType.AllDungeonsAndRaids
                                strDungeon = "all"
                            Case DungeonType.DungeonsOnly
                                strDungeon = "dungeons"
                            Case DungeonType.RaidsOnly
                                strDungeon = "raids"
                            Case DungeonType.BadgeOfJusticeRewards
                                strDungeon = "badgeofjustice"
                            Case DungeonType.EmblemOfHeroism
                                strDungeon = "emblemofheroism"
                            Case DungeonType.EmblemOfValor
                                strDungeon = "emblemofvalor"
                        End Select
                        strDifficulty = "all"
                    End Set
                End Property

                ''' <summary>
                ''' The boss to search for item drops from
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Boss() As Integer
                    Get
                        Return intBoss
                    End Get
                    Set(ByVal value As Integer)
                        Clear()
                        strSource = "dungeon"
                        intBoss = value
                        strDifficulty = "all"
                    End Set
                End Property

                ''' <summary>
                ''' The difficulty type of the dungeon to search for item drops from
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Difficulty() As DifficultyType
                    Get
                        Select Case strDifficulty
                            Case "normal"
                                Return DifficultyType.NormalOnly
                            Case "heroic"
                                Return DifficultyType.HeroicOnly
                            Case Else
                                Return DifficultyType.NormalAndHeroic
                        End Select
                    End Get
                    Set(ByVal value As DifficultyType)
                        If strSource <> "dungeon" Then
                            Throw New InvalidOperationException("The Difficulty filter is only valid for dungeons or raids.")
                            Exit Property
                        End If
                        If strDungeon <> "dungeons" And strDungeon <> "raids" Then
                            If Not IsNumeric(strDungeon) Then
                                Throw New InvalidOperationException("The Difficulty filter is only valid for dungeons or raids.")
                            End If
                            Dim dDungeons As New Dungeons
                            Dim varDungeon = (From d In dDungeons.Dungeons Where d.ID = Integer.Parse(strDungeon))
                            If varDungeon.Count = 0 Then
                                Throw New InvalidOperationException("Heroic difficulty is not available for this dungeon or raid.")
                                Exit Property
                            End If
                            If Not varDungeon.First().HasHeroic Then
                                Throw New InvalidOperationException("Heroic difficulty is not available for this dungeon or raid.")
                                Exit Property
                            End If
                        End If
                        Select Case value
                            Case DifficultyType.NormalAndHeroic
                                strDifficulty = "all"
                            Case DifficultyType.NormalOnly
                                strDifficulty = "normal"
                            Case DifficultyType.HeroicOnly
                                strDifficulty = "heroic"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The faction to search for items in
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Faction() As Integer
                    Get
                        If strSource = "reputation" And IsNumeric(strFaction) Then
                            Return Integer.Parse(strFaction)
                        Else
                            Return 0
                        End If
                    End Get
                    Set(ByVal value As Integer)
                        Clear()
                        strSource = "reputation"
                        If value = 0 Then
                            strFaction = "-1"
                        Else
                            strFaction = value.ToString()
                        End If
                    End Set
                End Property

                ''' <summary>
                ''' The type of PvP Alliance items to look for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property PvpAllianceSource() As PvpAllianceSourceType
                    Get
                        If strSource = "pvpAlliance" Then
                            Select Case strPvp
                                Case "wintergrasp"
                                    Return PvpAllianceSourceType.Wintergrasp
                                Case "arena4"
                                    Return PvpAllianceSourceType.ArenaSeason4
                                Case "arena3"
                                    Return PvpAllianceSourceType.ArenaSeason3
                                Case "arena2"
                                    Return PvpAllianceSourceType.ArenaSeason2
                                Case "honor"
                                    Return PvpAllianceSourceType.HonorRewards
                                Case "ab"
                                    Return PvpAllianceSourceType.ArathiBasin
                                Case "av"
                                    Return PvpAllianceSourceType.AlteracVally
                                Case "wsg"
                                    Return PvpAllianceSourceType.WarsongGulch
                                Case "halaa"
                                    Return PvpAllianceSourceType.Halaa
                                Case "honorhold"
                                    Return PvpAllianceSourceType.HonorHold
                                Case "terrokar" 'Incorrect spelling is intentional, this is how the Armory has it spelled.
                                    Return PvpAllianceSourceType.Terokkar
                                Case "zangarmarsh"
                                    Return PvpAllianceSourceType.Zangarmarsh
                                Case Else
                                    Return PvpAllianceSourceType.AllPvpSources
                            End Select
                        Else
                            Return PvpAllianceSourceType.AllPvpSources
                        End If
                    End Get
                    Set(ByVal value As PvpAllianceSourceType)
                        Clear()
                        strSource = "pvpAlliance"
                        Select Case value
                            Case PvpAllianceSourceType.AllPvpSources
                                strPvp = "all"
                            Case PvpAllianceSourceType.Wintergrasp
                                strPvp = "wintergrasp"
                            Case PvpAllianceSourceType.ArenaSeason4
                                strPvp = "arena4"
                            Case PvpAllianceSourceType.ArenaSeason3
                                strPvp = "arena3"
                            Case PvpAllianceSourceType.ArenaSeason2
                                strPvp = "arena2"
                            Case PvpAllianceSourceType.HonorRewards
                                strPvp = "honor"
                            Case PvpAllianceSourceType.ArathiBasin
                                strPvp = "ab"
                            Case PvpAllianceSourceType.AlteracVally
                                strPvp = "av"
                            Case PvpAllianceSourceType.WarsongGulch
                                strPvp = "wsg"
                            Case PvpAllianceSourceType.Halaa
                                strPvp = "halaa"
                            Case PvpAllianceSourceType.HonorHold
                                strPvp = "honorhold"
                            Case PvpAllianceSourceType.Terokkar
                                strPvp = "terrokar" 'Incorrect spelling is intentional, this is how the Armory has it spelled.
                            Case PvpAllianceSourceType.Zangarmarsh
                                strPvp = "zangarmarsh"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of PvP Horde items to look for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property PvpHordeSource() As PvpHordeSourceType
                    Get
                        If strSource = "pvpHorde" Then
                            Select Case strPvp
                                Case "wintergrasp"
                                    Return PvpHordeSourceType.Wintergrasp
                                Case "arena4"
                                    Return PvpHordeSourceType.ArenaSeason4
                                Case "arena3"
                                    Return PvpHordeSourceType.ArenaSeason3
                                Case "arena2"
                                    Return PvpHordeSourceType.ArenaSeason2
                                Case "honor"
                                    Return PvpHordeSourceType.HonorRewards
                                Case "ab"
                                    Return PvpHordeSourceType.ArathiBasin
                                Case "av"
                                    Return PvpHordeSourceType.AlteracVally
                                Case "wsg"
                                    Return PvpHordeSourceType.WarsongGulch
                                Case "halaa"
                                    Return PvpHordeSourceType.Halaa
                                Case "thrallmar"
                                    Return PvpHordeSourceType.Thrallmar
                                Case "terrokar" 'Incorrect spelling is intentional, this is how the Armory has it spelled.
                                    Return PvpHordeSourceType.Terokkar
                                Case "zangarmarsh"
                                    Return PvpHordeSourceType.Zangarmarsh
                                Case Else
                                    Return PvpHordeSourceType.AllPvpSources
                            End Select
                        Else
                            Return PvpHordeSourceType.AllPvpSources
                        End If
                    End Get
                    Set(ByVal value As PvpHordeSourceType)
                        Clear()
                        strSource = "pvpHorde"
                        Select Case value
                            Case PvpHordeSourceType.AllPvpSources
                                strPvp = "all"
                            Case PvpHordeSourceType.Wintergrasp
                                strPvp = "wintergrasp"
                            Case PvpHordeSourceType.ArenaSeason4
                                strPvp = "arena4"
                            Case PvpHordeSourceType.ArenaSeason3
                                strPvp = "arena3"
                            Case PvpHordeSourceType.ArenaSeason2
                                strPvp = "arena2"
                            Case PvpHordeSourceType.HonorRewards
                                strPvp = "honor"
                            Case PvpHordeSourceType.ArathiBasin
                                strPvp = "ab"
                            Case PvpHordeSourceType.AlteracVally
                                strPvp = "av"
                            Case PvpHordeSourceType.WarsongGulch
                                strPvp = "wsg"
                            Case PvpHordeSourceType.Halaa
                                strPvp = "halaa"
                            Case PvpHordeSourceType.Thrallmar
                                strPvp = "thrallmar"
                            Case PvpHordeSourceType.Terokkar
                                strPvp = "terrokar" 'Incorrect spelling is intentional, this is how the Armory has it spelled.
                            Case PvpHordeSourceType.Zangarmarsh
                                strPvp = "zangarmarsh"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' A function that clears the current filter
                ''' </summary>
                ''' <remarks></remarks>
                Public Sub Clear()
                    strSource = "all"
                    strDungeon = ""
                    intBoss = 0
                    strDifficulty = ""
                    strFaction = ""
                    strPvp = ""
                End Sub

            End Class

            ''' <summary>
            ''' A class that encapsulates the Armory's item type filters
            ''' </summary>
            ''' <remarks></remarks>
            Public Class ItemTypeFilter

                Friend strItemType As String = "all"
                Friend intDesiredBy As Integer
                Friend strDesiredByRole As String
                Friend strRarity As String
                Friend strWeaponSlot As String
                Friend strWeaponType As String
                Friend intRequiredLevelMin As Integer
                Friend intRequiredLevelMax As Integer
                Friend strArmorSlot As String
                Friend strArmorType As String
                Friend strGemType As String
                Friend strBagType As String
                Friend strProjectilesType As String
                Friend strQuiversType As String
                Friend strRecipesType As String
                Friend intSkillLevelMin As Integer
                Friend intSkillLevelMax As Integer
                Friend strPermanentEnchantmentSlot As String

                Private Shared strItemTypesWithDesiredBy() As String = {"all", "weapons", "armor", "gems", "glyphs"}
                Private Shared intDesiredByWithRole() As Integer = {6, 11, 2, 5, 7, 1}
                Private Shared intDesiredByWithRoleTank() As Integer = {6, 11, 2, 1}
                Private Shared intDesiredByWithRoleMeleeDPS() As Integer = {6, 11, 2, 7, 1}
                Private Shared intDesiredByWithRoleCasterDPS() As Integer = {11, 2, 5, 7}
                Private Shared intDesiredByWithRoleHealer() As Integer = {11, 2, 5, 7}
                Private Shared strItemTypesWithRarity() As String = {"all", "weapons", "armor", "gems", "consumables", "tradegoods", "projectiles", "recipes", "reagents", "misc", "enchP", "enchT"}
                Private Shared strItemTypesWithRequiredLevel() As String = {"weapons", "armor"}

                ''' <summary>
                ''' The type of the items to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property ItemType() As ItemTypeType
                    Get
                        Select Case strItemType
                            Case "weapons"
                                Return ItemTypeType.Weapons
                            Case "armor"
                                Return ItemTypeType.Armor
                            Case "gems"
                                Return ItemTypeType.Gems
                            Case "containers"
                                Return ItemTypeType.Containers
                            Case "consumables"
                                Return ItemTypeType.Consumables
                            Case "tradegoods"
                                Return ItemTypeType.TradeGoods
                            Case "projectiles"
                                Return ItemTypeType.Projectiles
                            Case "quivers"
                                Return ItemTypeType.Quivers
                            Case "recipes"
                                Return ItemTypeType.Recipes
                            Case "reagents"
                                Return ItemTypeType.Reagents
                            Case "misc"
                                Return ItemTypeType.Miscellaneous
                            Case "enchP"
                                Return ItemTypeType.EnchantmentsPermanent
                            Case "enchT"
                                Return ItemTypeType.EnchantmentsTemporary
                            Case "mounts"
                                Return ItemTypeType.Mounts
                            Case "smallpets"
                                Return ItemTypeType.SmallPets
                            Case "keys"
                                Return ItemTypeType.Keys
                            Case "glyphs"
                                Return ItemTypeType.Glyphs
                            Case Else
                                Return ItemTypeType.AllItems
                        End Select
                    End Get
                    Set(ByVal value As ItemTypeType)
                        Clear()
                        Select Case value
                            Case ItemTypeType.Weapons
                                strItemType = "weapons"
                            Case ItemTypeType.Armor
                                strItemType = "armor"
                            Case ItemTypeType.Gems
                                strItemType = "gems"
                            Case ItemTypeType.Containers
                                strItemType = "containers"
                            Case ItemTypeType.Consumables
                                strItemType = "consumables"
                            Case ItemTypeType.TradeGoods
                                strItemType = "tradegoods"
                            Case ItemTypeType.Projectiles
                                strItemType = "projectiles"
                            Case ItemTypeType.Quivers
                                strItemType = "quivers"
                            Case ItemTypeType.Recipes
                                strItemType = "recipes"
                            Case ItemTypeType.Reagents
                                strItemType = "reagents"
                            Case ItemTypeType.Miscellaneous
                                strItemType = "misc"
                            Case ItemTypeType.EnchantmentsPermanent
                                strItemType = "enchP"
                            Case ItemTypeType.EnchantmentsTemporary
                                strItemType = "enchT"
                            Case ItemTypeType.Mounts
                                strItemType = "mounts"
                            Case ItemTypeType.SmallPets
                                strItemType = "smallpets"
                            Case ItemTypeType.Keys
                                strItemType = "keys"
                            Case ItemTypeType.Glyphs
                                strItemType = "glyphs"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The class that the items to search for should be desired by
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property DesiredBy() As DesiredByType
                    Get
                        Return CType(intDesiredBy, DesiredByType)
                    End Get
                    Set(ByVal value As DesiredByType)
                        If (From i In strItemTypesWithDesiredBy Where i.ToString() = strItemType).Count() = 0 Then
                            Throw New InvalidOperationException("The DesiredBy filter is only valid for ItemType values AllItems, Weapons, Armor, Gems, and Glyphs.")
                            Exit Property
                        End If
                        strDesiredByRole = ""
                        intDesiredBy = CType(value, Integer)
                    End Set
                End Property

                ''' <summary>
                ''' The role of the class the items to search for should be desired by
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property DesiredByRole() As DesiredByRoleType
                    Get
                        Select Case strDesiredByRole
                            Case "tank"
                                Return DesiredByRoleType.Tank
                            Case "melee"
                                Return DesiredByRoleType.MeleeDPS
                            Case "caster"
                                Return DesiredByRoleType.CasterDPS
                            Case "healer"
                                Return DesiredByRoleType.Healer
                            Case Else
                                Return DesiredByRoleType.AnyType
                        End Select
                    End Get
                    Set(ByVal value As DesiredByRoleType)
                        If (From i In intDesiredByWithRole Where i = intDesiredBy).Count() = 0 Then
                            Throw New InvalidOperationException("The DesiredByRole filter is only valid for DesiredBy values DeathKnight, Druid, Paladin, Priest, Shaman, and Warrior.")
                            Exit Property
                        End If
                        Select Case value
                            Case DesiredByRoleType.AnyType
                                strDesiredByRole = ""
                            Case DesiredByRoleType.Tank
                                If (From i In intDesiredByWithRoleTank Where i = intDesiredBy).Count() = 0 Then
                                    Throw New InvalidOperationException("You DesiredByRole value of Tank is only valid for DesiredBy values DeathKnight, Druid, Paladin, and Warrior.")
                                    Exit Property
                                End If
                                strDesiredByRole = "tank"
                            Case DesiredByRoleType.MeleeDPS
                                If (From i In intDesiredByWithRoleMeleeDPS Where i = intDesiredBy).Count() = 0 Then
                                    Throw New InvalidOperationException("You DesiredByRole value of MeleeDPS is only valid for DesiredBy values DeathKnight, Druid, Paladin, Shaman, and Warrior.")
                                    Exit Property
                                End If
                                strDesiredByRole = "melee"
                            Case DesiredByRoleType.CasterDPS
                                If (From i In intDesiredByWithRoleCasterDPS Where i = intDesiredBy).Count() = 0 Then
                                    Throw New InvalidOperationException("You DesiredByRole value of CasterDPS is only valid for DesiredBy values Druid, Paladin, Priest, and Shaman.")
                                    Exit Property
                                End If
                                strDesiredByRole = "caster"
                            Case DesiredByRoleType.Healer
                                If (From i In intDesiredByWithRoleHealer Where i = intDesiredBy).Count() = 0 Then
                                    Throw New InvalidOperationException("You DesiredByRole value of Healer is only valid for DesiredBy values Druid, Paladin, Priest, and Shaman.")
                                    Exit Property
                                End If
                                strDesiredByRole = "healer"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The rarity of the items to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Rarity() As RarityType
                    Get
                        Select Case strRarity
                            Case "pr"
                                Return RarityType.Poor
                            Case "cn"
                                Return RarityType.Common
                            Case "un"
                                Return RarityType.Uncommon
                            Case "re"
                                Return RarityType.Rare
                            Case "ec"
                                Return RarityType.Epic
                            Case "lg"
                                Return RarityType.Legendary
                            Case "hm"
                                Return RarityType.Heirloom
                            Case Else
                                Return RarityType.All
                        End Select
                    End Get
                    Set(ByVal value As RarityType)
                        If (From i In strItemTypesWithRarity Where i.ToString() = strItemType).Count() = 0 Then
                            Throw New InvalidOperationException("The Rarity filter is only valid for ItemType values AllItems, Weapons, Armor, Gems, Consumables, TradeGoods, Projectiles, Recipes, Reagents, Miscellaneous, EnchantmentsPermanent, and EnchantmentsTemporary.")
                            Exit Property
                        End If
                        Select Case value
                            Case RarityType.All
                                strRarity = ""
                            Case RarityType.Poor
                                strRarity = "pr"
                            Case RarityType.Common
                                strRarity = "cn"
                            Case RarityType.Uncommon
                                strRarity = "un"
                            Case RarityType.Rare
                                strRarity = "re"
                            Case RarityType.Epic
                                strRarity = "ec"
                            Case RarityType.Legendary
                                strRarity = "lg"
                            Case RarityType.Heirloom
                                strRarity = "hm"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The slot of the weapons to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property WeaponSlot() As WeaponSlotType
                    Get
                        Select Case strWeaponSlot
                            Case "main"
                                Return WeaponSlotType.MainHand
                            Case "off"
                                Return WeaponSlotType.OffHand
                            Case "one"
                                Return WeaponSlotType.MainOrOffHand
                            Case "two"
                                Return WeaponSlotType.TwoHanded
                            Case "ranged"
                                Return WeaponSlotType.Ranged
                            Case Else
                                Return WeaponSlotType.AllSlots
                        End Select
                    End Get
                    Set(ByVal value As WeaponSlotType)
                        If strItemType <> "weapons" Then
                            Clear()
                        End If
                        strItemType = "weapons"
                        Select Case value
                            Case WeaponSlotType.AllSlots
                                strWeaponSlot = ""
                            Case WeaponSlotType.MainHand
                                strWeaponSlot = "main"
                            Case WeaponSlotType.OffHand
                                strWeaponSlot = "off"
                            Case WeaponSlotType.MainOrOffHand
                                strWeaponSlot = "one"
                            Case WeaponSlotType.TwoHanded
                                strWeaponSlot = "two"
                            Case WeaponSlotType.Ranged
                                strWeaponSlot = "ranged"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of the weapons to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property WeaponType() As WeaponTypeType
                    Get
                        Select Case strWeaponType
                            Case "1haxe"
                                Return WeaponTypeType.OneHandedAxes
                            Case "2haxe"
                                Return WeaponTypeType.TwoHandedAxes
                            Case "bow"
                                Return WeaponTypeType.Bows
                            Case "gun"
                                Return WeaponTypeType.Guns
                            Case "1hmce"
                                Return WeaponTypeType.OneHandedMaces
                            Case "2hmce"
                                Return WeaponTypeType.TwoHandedMaces
                            Case "plarm"
                                Return WeaponTypeType.Polearms
                            Case "1hswd"
                                Return WeaponTypeType.OneHandedSwords
                            Case "2hswd"
                                Return WeaponTypeType.TwoHandedSwords
                            Case "stv"
                                Return WeaponTypeType.Staves
                            Case "fwpn"
                                Return WeaponTypeType.FistWeapons
                            Case "misc"
                                Return WeaponTypeType.Miscellanous
                            Case "dggr"
                                Return WeaponTypeType.Daggers
                            Case "thrwn"
                                Return WeaponTypeType.Thrown
                            Case "xbow"
                                Return WeaponTypeType.Crossbows
                            Case "wnd"
                                Return WeaponTypeType.Wands
                            Case "fshpl"
                                Return WeaponTypeType.FishingPole
                            Case Else
                                Return WeaponTypeType.AllWeaponTypes
                        End Select
                    End Get
                    Set(ByVal value As WeaponTypeType)
                        If strItemType <> "weapons" Then
                            Clear()
                        End If
                        strItemType = "weapons"
                        Select Case value
                            Case WeaponTypeType.OneHandedAxes
                                strWeaponType = "1haxe"
                            Case WeaponTypeType.TwoHandedAxes
                                strWeaponType = "2haxe"
                            Case WeaponTypeType.Bows
                                strWeaponType = "bow"
                            Case WeaponTypeType.Guns
                                strWeaponType = "gun"
                            Case WeaponTypeType.OneHandedMaces
                                strWeaponType = "1hmce"
                            Case WeaponTypeType.TwoHandedMaces
                                strWeaponType = "2hmce"
                            Case WeaponTypeType.Polearms
                                strWeaponType = "plarm"
                            Case WeaponTypeType.OneHandedSwords
                                strWeaponType = "1hswd"
                            Case WeaponTypeType.TwoHandedSwords
                                strWeaponType = "2hswd"
                            Case WeaponTypeType.Staves
                                strWeaponType = "stv"
                            Case WeaponTypeType.FistWeapons
                                strWeaponType = "fwpn"
                            Case WeaponTypeType.Miscellanous
                                strWeaponType = "misc"
                            Case WeaponTypeType.Daggers
                                strWeaponType = "dggr"
                            Case WeaponTypeType.Thrown
                                strWeaponType = "thrwn"
                            Case WeaponTypeType.Crossbows
                                strWeaponType = "xbow"
                            Case WeaponTypeType.Wands
                                strWeaponType = "wnd"
                            Case WeaponTypeType.FishingPole
                                strWeaponType = "fshpl"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The minimum required level of the items to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property RequiredLevelMin() As Integer
                    Get
                        Return intRequiredLevelMin
                    End Get
                    Set(ByVal value As Integer)
                        If (From i In strItemTypesWithRequiredLevel Where i.ToString() = strItemType).Count() = 0 Then
                            Throw New InvalidOperationException("The Required Level filter is only valid for ItemType values Weapons and Armor.")
                            Exit Property
                        End If

                        If value < 0 Or value > 80 Then
                            Throw New ArgumentOutOfRangeException("RequiredLevelMin", "The Required Level must set be between 1 and 80, or set to 0 to ignore the filter.")
                            Exit Property
                        End If

                        intRequiredLevelMin = value
                    End Set
                End Property

                ''' <summary>
                ''' The maximum required level of the items to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property RequiredLevelMax() As Integer
                    Get
                        Return intRequiredLevelMax
                    End Get
                    Set(ByVal value As Integer)
                        If (From i In strItemTypesWithRequiredLevel Where i.ToString() = strItemType).Count() = 0 Then
                            Throw New InvalidOperationException("The Required Level filter is only valid for ItemType values Weapons and Armor.")
                            Exit Property
                        End If

                        If value < 0 Or value > 80 Then
                            Throw New ArgumentOutOfRangeException("RequiredLevelMax", "The Required Level must be set between 1 and 80, or set to 0 to ignore the filter.")
                            Exit Property
                        End If

                        intRequiredLevelMax = value
                    End Set
                End Property

                ''' <summary>
                ''' The slot of the armor to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property ArmorSlot() As ArmorSlotType
                    Get
                        Select Case strArmorSlot
                            Case "head"
                                Return ArmorSlotType.Head
                            Case "neck"
                                Return ArmorSlotType.Neck
                            Case "shoulders"
                                Return ArmorSlotType.Shoulders
                            Case "back"
                                Return ArmorSlotType.Back
                            Case "chest"
                                Return ArmorSlotType.Chest
                            Case "shirt"
                                Return ArmorSlotType.Shirt
                            Case "wrists"
                                Return ArmorSlotType.Wrists
                            Case "hands"
                                Return ArmorSlotType.Hands
                            Case "waist"
                                Return ArmorSlotType.Waist
                            Case "legs"
                                Return ArmorSlotType.Legs
                            Case "feet"
                                Return ArmorSlotType.Feet
                            Case "finger"
                                Return ArmorSlotType.Finger
                            Case "trinket"
                                Return ArmorSlotType.Trinket
                            Case "offhand"
                                Return ArmorSlotType.OffHandFrill
                            Case Else
                                Return ArmorSlotType.AllSlots
                        End Select
                    End Get
                    Set(ByVal value As ArmorSlotType)
                        If strItemType <> "armor" Then
                            Clear()
                        End If
                        strItemType = "armor"
                        Select Case value
                            Case ArmorSlotType.AllSlots
                                strArmorSlot = ""
                            Case ArmorSlotType.Head
                                strArmorSlot = "head"
                            Case ArmorSlotType.Neck
                                strArmorSlot = "neck"
                            Case ArmorSlotType.Shoulders
                                strArmorSlot = "shoulders"
                            Case ArmorSlotType.Back
                                strArmorSlot = "back"
                            Case ArmorSlotType.Chest
                                strArmorSlot = "chest"
                            Case ArmorSlotType.Shirt
                                strArmorSlot = "shirt"
                            Case ArmorSlotType.Wrists
                                strArmorSlot = "wrists"
                            Case ArmorSlotType.Hands
                                strArmorSlot = "hands"
                            Case ArmorSlotType.Waist
                                strArmorSlot = "waist"
                            Case ArmorSlotType.Legs
                                strArmorSlot = "legs"
                            Case ArmorSlotType.Feet
                                strArmorSlot = "feet"
                            Case ArmorSlotType.Finger
                                strArmorSlot = "finger"
                            Case ArmorSlotType.Trinket
                                strArmorSlot = "trinket"
                            Case ArmorSlotType.OffHandFrill
                                strArmorSlot = "offhand"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of the armor to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property ArmorType() As ArmorTypeType
                    Get
                        Select Case strArmorType
                            Case "cloth"
                                Return ArmorTypeType.Cloth
                            Case "leather"
                                Return ArmorTypeType.Leather
                            Case "mail"
                                Return ArmorTypeType.Mail
                            Case "plate"
                                Return ArmorTypeType.Plate
                            Case "shield"
                                Return ArmorTypeType.Shield
                            Case "idol"
                                Return ArmorTypeType.Idol
                            Case "libram"
                                Return ArmorTypeType.Libram
                            Case "totem"
                                Return ArmorTypeType.Totem
                            Case "sigil"
                                Return ArmorTypeType.Sigil
                            Case "miscellaneous"
                                Return ArmorTypeType.Miscellaneous
                            Case Else
                                Return ArmorTypeType.AllArmorTypes
                        End Select
                    End Get
                    Set(ByVal value As ArmorTypeType)
                        If strItemType <> "armor" Then
                            Clear()
                        End If
                        strItemType = "armor"
                        Select Case value
                            Case ArmorTypeType.AllArmorTypes
                                strArmorType = ""
                            Case ArmorTypeType.Cloth
                                strArmorType = "cloth"
                            Case ArmorTypeType.Leather
                                strArmorType = "leather"
                            Case ArmorTypeType.Mail
                                strArmorType = "mail"
                            Case ArmorTypeType.Plate
                                strArmorType = "plate"
                            Case ArmorTypeType.Shield
                                strArmorType = "shield"
                            Case ArmorTypeType.Idol
                                strArmorType = "idol"
                            Case ArmorTypeType.Libram
                                strArmorType = "libram"
                            Case ArmorTypeType.Totem
                                strArmorType = "totem"
                            Case ArmorTypeType.Sigil
                                strArmorType = "sigil"
                            Case ArmorTypeType.Miscellaneous
                                strArmorType = "miscellaneous"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of gem to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property GemType() As GemTypeType
                    Get
                        Select Case strGemType
                            Case "blue"
                                Return GemTypeType.Blue
                            Case "red"
                                Return GemTypeType.Red
                            Case "yellow"
                                Return GemTypeType.Yellow
                            Case "meta"
                                Return GemTypeType.Meta
                            Case "green"
                                Return GemTypeType.Green
                            Case "orange"
                                Return GemTypeType.Orange
                            Case "purple"
                                Return GemTypeType.Purple
                            Case "prismatic"
                                Return GemTypeType.Prismatic
                            Case Else
                                Return GemTypeType.AllGemTypes
                        End Select
                    End Get
                    Set(ByVal value As GemTypeType)
                        Clear()
                        strItemType = "gems"
                        Select Case value
                            Case GemTypeType.AllGemTypes
                                strGemType = ""
                            Case GemTypeType.Blue
                                strGemType = "blue"
                            Case GemTypeType.Red
                                strGemType = "red"
                            Case GemTypeType.Yellow
                                strGemType = "yellow"
                            Case GemTypeType.Meta
                                strGemType = "meta"
                            Case GemTypeType.Green
                                strGemType = "green"
                            Case GemTypeType.Orange
                                strGemType = "orange"
                            Case GemTypeType.Purple
                                strGemType = "purple"
                            Case GemTypeType.Prismatic
                                strGemType = "prismatic"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of bag to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property ContainerType() As BagTypeType
                    Get
                        Select Case strBagType
                            Case "bag"
                                Return BagTypeType.Bag
                            Case "soul"
                                Return BagTypeType.SoulBag
                            Case "herb"
                                Return BagTypeType.HerbBag
                            Case "enchanting"
                                Return BagTypeType.EnchantingBag
                            Case "engineering"
                                Return BagTypeType.EngineeringBag
                            Case "gem"
                                Return BagTypeType.GemBag
                            Case "mining"
                                Return BagTypeType.MiningBag
                            Case Else
                                Return BagTypeType.AllBags
                        End Select
                    End Get
                    Set(ByVal value As BagTypeType)
                        Clear()
                        strItemType = "containers"
                        Select Case value
                            Case BagTypeType.AllBags
                                strBagType = ""
                            Case BagTypeType.Bag
                                strBagType = "bag"
                            Case BagTypeType.SoulBag
                                strBagType = "soul"
                            Case BagTypeType.HerbBag
                                strBagType = "herb"
                            Case BagTypeType.EnchantingBag
                                strBagType = "enchanting"
                            Case BagTypeType.EngineeringBag
                                strBagType = "engineering"
                            Case BagTypeType.GemBag
                                strBagType = "gem"
                            Case BagTypeType.MiningBag
                                strBagType = "mining"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of projectiles to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property ProjectilesType() As ProjectileTypeType
                    Get
                        Select Case strProjectilesType
                            Case "arrow"
                                Return ProjectileTypeType.Arrow
                            Case "bullet"
                                Return ProjectileTypeType.Bullet
                            Case Else
                                Return ProjectileTypeType.AllProjectiles
                        End Select
                    End Get
                    Set(ByVal value As ProjectileTypeType)
                        Clear()
                        strItemType = "projectiles"
                        Select Case value
                            Case ProjectileTypeType.AllProjectiles
                                strProjectilesType = ""
                            Case ProjectileTypeType.Arrow
                                strProjectilesType = "arrow"
                            Case ProjectileTypeType.Bullet
                                strProjectilesType = "bullet"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of quiver to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property QuiverType() As QuiverTypeType
                    Get
                        Select Case strQuiversType
                            Case "quiver"
                                Return QuiverTypeType.Quiver
                            Case "ammopouch"
                                Return QuiverTypeType.AmmoPouch
                            Case Else
                                Return QuiverTypeType.AllQuivers
                        End Select
                    End Get
                    Set(ByVal value As QuiverTypeType)
                        Clear()
                        strItemType = "quivers"
                        Select Case value
                            Case QuiverTypeType.AllQuivers
                                strQuiversType = ""
                            Case QuiverTypeType.Quiver
                                strQuiversType = "quiver"
                            Case QuiverTypeType.AmmoPouch
                                strQuiversType = "ammopouch"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of recipe to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property RecipesType() As RecipesTypeType
                    Get
                        Select Case strRecipesType
                            Case "books"
                                Return RecipesTypeType.Books
                            Case "leatherworking"
                                Return RecipesTypeType.Leatherworking
                            Case "tailoring"
                                Return RecipesTypeType.Tailoring
                            Case "engineering"
                                Return RecipesTypeType.Engineering
                            Case "blacksmithing"
                                Return RecipesTypeType.Blacksmithing
                            Case "cooking"
                                Return RecipesTypeType.Cooking
                            Case "alchemy"
                                Return RecipesTypeType.Alchemy
                            Case "firstaid"
                                Return RecipesTypeType.FirstAid
                            Case "enchanting"
                                Return RecipesTypeType.Enchanting
                            Case "fishing"
                                Return RecipesTypeType.Fishing
                            Case "jewelcrafting"
                                Return RecipesTypeType.Jewelcrafting
                            Case Else
                                Return RecipesTypeType.AllRecipes
                        End Select
                    End Get
                    Set(ByVal value As RecipesTypeType)
                        If strItemType <> "recipes" Then
                            Clear()
                        End If
                        strItemType = "recipes"
                        Select Case value
                            Case RecipesTypeType.AllRecipes
                                strRecipesType = ""
                            Case RecipesTypeType.Books
                                strRecipesType = "books"
                            Case RecipesTypeType.Leatherworking
                                strRecipesType = "leatherworking"
                            Case RecipesTypeType.Tailoring
                                strRecipesType = "tailoring"
                            Case RecipesTypeType.Engineering
                                strRecipesType = "engineering"
                            Case RecipesTypeType.Blacksmithing
                                strRecipesType = "blacksmithing"
                            Case RecipesTypeType.Cooking
                                strRecipesType = "cooking"
                            Case RecipesTypeType.Alchemy
                                strRecipesType = "alchemy"
                            Case RecipesTypeType.FirstAid
                                strRecipesType = "firstaid"
                            Case RecipesTypeType.Enchanting
                                strRecipesType = "enchanting"
                            Case RecipesTypeType.Fishing
                                strRecipesType = "fishing"
                            Case RecipesTypeType.Jewelcrafting
                                strRecipesType = "jewelcrafting"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The minimum skill level of the recipes to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property SkillLevelMin() As Integer
                    Get
                        Return intSkillLevelMin
                    End Get
                    Set(ByVal value As Integer)
                        If intSkillLevelMin < 0 Or intSkillLevelMin > 450 Then
                            Throw New ArgumentOutOfRangeException("SkillLevelMin", "The Skill Level must be set between 1 and 450, or set to 0 to ignore the filter.")
                            Exit Property
                        End If

                        If strItemType <> "recipes" Then
                            Clear()
                        End If
                        strItemType = "recipes"
                        intSkillLevelMin = value
                    End Set
                End Property

                ''' <summary>
                ''' The maximum skill level of the recipes to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property SkillLevelMax() As Integer
                    Get
                        Return intSkillLevelMax
                    End Get
                    Set(ByVal value As Integer)
                        If intSkillLevelMax < 0 Or intSkillLevelMax > 450 Then
                            Throw New ArgumentOutOfRangeException("SkillLevelMax", "The Skill Level must be set between 1 and 450, or set to 0 to ignore the filter.")
                            Exit Property
                        End If

                        If strItemType <> "recipes" Then
                            Clear()
                        End If
                        strItemType = "recipes"
                        intSkillLevelMax = value
                    End Set
                End Property

                ''' <summary>
                ''' The slot of the permanent enchantment to search for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property PermanentEnchantmentSlot() As PermanentEnchantmentSlotType
                    Get
                        Select Case strPermanentEnchantmentSlot
                            Case "head"
                                Return PermanentEnchantmentSlotType.Head
                            Case "shoulders"
                                Return PermanentEnchantmentSlotType.Shoulders
                            Case "chest"
                                Return PermanentEnchantmentSlotType.Chest
                            Case "back"
                                Return PermanentEnchantmentSlotType.Back
                            Case "hands"
                                Return PermanentEnchantmentSlotType.Hands
                            Case "wrists"
                                Return PermanentEnchantmentSlotType.Wrists
                            Case "legs"
                                Return PermanentEnchantmentSlotType.Legs
                            Case "feet"
                                Return PermanentEnchantmentSlotType.Feet
                            Case "weapon"
                                Return PermanentEnchantmentSlotType.Weapon
                            Case "shield"
                                Return PermanentEnchantmentSlotType.Shield
                            Case Else
                                Return PermanentEnchantmentSlotType.AllSlots
                        End Select
                    End Get
                    Set(ByVal value As PermanentEnchantmentSlotType)
                        Clear()
                        strItemType = "enchP"
                        Select Case value
                            Case PermanentEnchantmentSlotType.AllSlots
                                strPermanentEnchantmentSlot = ""
                            Case PermanentEnchantmentSlotType.Head
                                strPermanentEnchantmentSlot = "head"
                            Case PermanentEnchantmentSlotType.Shoulders
                                strPermanentEnchantmentSlot = "shoulders"
                            Case PermanentEnchantmentSlotType.Chest
                                strPermanentEnchantmentSlot = "chest"
                            Case PermanentEnchantmentSlotType.Back
                                strPermanentEnchantmentSlot = "back"
                            Case PermanentEnchantmentSlotType.Hands
                                strPermanentEnchantmentSlot = "hands"
                            Case PermanentEnchantmentSlotType.Wrists
                                strPermanentEnchantmentSlot = "wrists"
                            Case PermanentEnchantmentSlotType.Legs
                                strPermanentEnchantmentSlot = "legs"
                            Case PermanentEnchantmentSlotType.Feet
                                strPermanentEnchantmentSlot = "feet"
                            Case PermanentEnchantmentSlotType.Weapon
                                strPermanentEnchantmentSlot = "weapon"
                            Case PermanentEnchantmentSlotType.Shield
                                strPermanentEnchantmentSlot = "shield"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' A function that clears the current filter
                ''' </summary>
                ''' <remarks></remarks>
                Public Sub Clear()
                    strItemType = "all"
                    intDesiredBy = 0
                    strDesiredByRole = ""
                    strWeaponSlot = ""
                    strWeaponType = ""
                    intRequiredLevelMin = 0
                    intRequiredLevelMax = 0
                    strArmorSlot = ""
                    strArmorType = ""
                    strGemType = ""
                    strBagType = ""
                    strProjectilesType = ""
                    strQuiversType = ""
                    strRecipesType = ""
                    intSkillLevelMin = 0
                    intSkillLevelMax = 0
                    strPermanentEnchantmentSlot = ""
                End Sub

            End Class

            ''' <summary>
            ''' A class that encapsulates a single advanced option filter
            ''' </summary>
            ''' <remarks></remarks>
            Public Class AdvancedOptionsFilter

                Friend strAdvancedOptions As String
                Friend strOperator As String
                Friend intRange As Integer

                ''' <summary>
                ''' The type of advanced option to filter for
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property AdvancedOptions() As AdvancedOptionsType
                    Get
                        Select Case strAdvancedOptions
                            Case "strength"
                                Return AdvancedOptionsType.BaseStat_Strength
                            Case "agility"
                                Return AdvancedOptionsType.BaseStat_Agility
                            Case "stamina"
                                Return AdvancedOptionsType.BaseStat_Stamina
                            Case "intellect"
                                Return AdvancedOptionsType.BaseStat_Intellect
                            Case "spirit"
                                Return AdvancedOptionsType.BaseStat_Spirit
                            Case "critRating"
                                Return AdvancedOptionsType.General_CritRating
                            Case "hitRating"
                                Return AdvancedOptionsType.General_HitRating
                            Case "hasteRating"
                                Return AdvancedOptionsType.General_HasteRating
                            Case "attackPower"
                                Return AdvancedOptionsType.PhysicalCombat_AttackPower
                            Case "feralAttackPower"
                                Return AdvancedOptionsType.PhysicalCombat_FeralAttackPower
                            Case "ignoreArmor"
                                Return AdvancedOptionsType.PhysicalCombat_ArmorPenetration
                            Case "expertiseRating"
                                Return AdvancedOptionsType.PhysicalCombat_ExpertiseRating
                            Case "spellPower"
                                Return AdvancedOptionsType.Spell_SpellPower
                            Case "spellCritRating"
                                Return AdvancedOptionsType.Spell_SpellCritRating
                            Case "spellHitRating"
                                Return AdvancedOptionsType.Spell_SpellHitRating
                            Case "spellPenetration"
                                Return AdvancedOptionsType.Spell_Penetration
                            Case "spellManaRegen"
                                Return AdvancedOptionsType.Spell_ManaRegen
                            Case "spellHasteRating"
                                Return AdvancedOptionsType.Spell_SpellHasteRating
                            Case "spellDamageArcane"
                                Return AdvancedOptionsType.Spell_ArcaneDamage
                            Case "spellDamageHoly"
                                Return AdvancedOptionsType.Spell_HolyDamage
                            Case "spellDamageShadow"
                                Return AdvancedOptionsType.Spell_ShadowDamage
                            Case "spellDamageNature"
                                Return AdvancedOptionsType.Spell_NatureDamage
                            Case "spellDamageFrost"
                                Return AdvancedOptionsType.Spell_FrostDamage
                            Case "spellDamageFire"
                                Return AdvancedOptionsType.Spell_FireDamage
                            Case "armor"
                                Return AdvancedOptionsType.Defense_Armor
                            Case "blockRating"
                                Return AdvancedOptionsType.Defense_BlockRating
                            Case "blockValue"
                                Return AdvancedOptionsType.Defense_BlockValue
                            Case "defenseRating"
                                Return AdvancedOptionsType.Defense_DefenseRating
                            Case "dodgeRating"
                                Return AdvancedOptionsType.Defense_DodgeRating
                            Case "parryRating"
                                Return AdvancedOptionsType.Defense_ParryRating
                            Case "healthRegen"
                                Return AdvancedOptionsType.Defense_HealthRegen
                            Case "resilience"
                                Return AdvancedOptionsType.Defense_Resilience
                            Case "resistArcane"
                                Return AdvancedOptionsType.Resistance_ArcaneResist
                            Case "resistShadow"
                                Return AdvancedOptionsType.Resistance_ShadowResist
                            Case "resistNature"
                                Return AdvancedOptionsType.Resistance_NatureResist
                            Case "resistFrost"
                                Return AdvancedOptionsType.Resistance_FrostResist
                            Case "resistFire"
                                Return AdvancedOptionsType.Resistance_FireResist
                            Case "dps"
                                Return AdvancedOptionsType.Weapon_Dps
                            Case "minDamage"
                                Return AdvancedOptionsType.Weapon_MinDamage
                            Case "maxDamage"
                                Return AdvancedOptionsType.Weapon_MaxDamage
                            Case "speed"
                                Return AdvancedOptionsType.Weapon_Speed
                            Case "bindsPickedUp"
                                Return AdvancedOptionsType.General_BindOnPickup
                            Case "bindsEquip"
                                Return AdvancedOptionsType.General_BindOnEquip
                            Case "bindsWhenUsed"
                                Return AdvancedOptionsType.General_BindOnUse
                            Case "unique"
                                Return AdvancedOptionsType.General_Unique
                            Case "uniqueEquipped"
                                Return AdvancedOptionsType.General_UniqueEquipped
                            Case "hasSpellEffect_resist"
                                Return AdvancedOptionsType.General_SpellEffect_ChanceToResist
                            Case "hasSpellEffect_interrupt"
                                Return AdvancedOptionsType.General_SpellEffect_AvoidInterruption
                            Case "hasSpellEffect_proc"
                                Return AdvancedOptionsType.General_SpellEffect_ChanceOnHitOrCast
                            Case "hasSpellEffect_dispel"
                                Return AdvancedOptionsType.General_SpellEffect_DispelEffects
                            Case "hasSpellEffect_cooldown"
                                Return AdvancedOptionsType.General_SpellEffect_ReduceCooldown
                            Case "hasSpellEffect_casttime"
                                Return AdvancedOptionsType.General_SpellEffect_ReduceCastTime
                            Case "hasSpellEffect_spellcost"
                                Return AdvancedOptionsType.General_SpellEffect_ReduceSpellCost
                            Case "hasSpellEffect_duration"
                                Return AdvancedOptionsType.General_SpellEffect_IncreaseDuration
                            Case "hasSpellEffect_range"
                                Return AdvancedOptionsType.General_SpellEffect_IncreaseRange
                            Case "hasSpellEffect_threat"
                                Return AdvancedOptionsType.General_SpellEffect_ReduceThreat
                            Case "hasSpellEffect_group"
                                Return AdvancedOptionsType.General_SpellEffect_GroupBuff
                            Case "hasSpellEffect_summon"
                                Return AdvancedOptionsType.General_SpellEffect_SummonCreature
                            Case Else
                                Return Nothing
                        End Select
                    End Get
                    Set(ByVal value As AdvancedOptionsType)
                        Select Case value
                            Case AdvancedOptionsType.BaseStat_Strength
                                strAdvancedOptions = "strength"
                            Case AdvancedOptionsType.BaseStat_Agility
                                strAdvancedOptions = "agility"
                            Case AdvancedOptionsType.BaseStat_Stamina
                                strAdvancedOptions = "stamina"
                            Case AdvancedOptionsType.BaseStat_Intellect
                                strAdvancedOptions = "intellect"
                            Case AdvancedOptionsType.BaseStat_Spirit
                                strAdvancedOptions = "spirit"
                            Case AdvancedOptionsType.General_CritRating
                                strAdvancedOptions = "critRating"
                            Case AdvancedOptionsType.General_HitRating
                                strAdvancedOptions = "hitRating"
                            Case AdvancedOptionsType.General_HasteRating
                                strAdvancedOptions = "hasteRating"
                            Case AdvancedOptionsType.PhysicalCombat_AttackPower
                                strAdvancedOptions = "attackPower"
                            Case AdvancedOptionsType.PhysicalCombat_FeralAttackPower
                                strAdvancedOptions = "feralAttackPower"
                            Case AdvancedOptionsType.PhysicalCombat_ArmorPenetration
                                strAdvancedOptions = "ignoreArmor"
                            Case AdvancedOptionsType.PhysicalCombat_ExpertiseRating
                                strAdvancedOptions = "expertiseRating"
                            Case AdvancedOptionsType.Spell_SpellPower
                                strAdvancedOptions = "spellPower"
                            Case AdvancedOptionsType.Spell_SpellCritRating
                                strAdvancedOptions = "spellCritRating"
                            Case AdvancedOptionsType.Spell_SpellHitRating
                                strAdvancedOptions = "spellHitRating"
                            Case AdvancedOptionsType.Spell_Penetration
                                strAdvancedOptions = "spellPenetration"
                            Case AdvancedOptionsType.Spell_ManaRegen
                                strAdvancedOptions = "spellManaRegen"
                            Case AdvancedOptionsType.Spell_SpellHasteRating
                                strAdvancedOptions = "spellHasteRating"
                            Case AdvancedOptionsType.Spell_ArcaneDamage
                                strAdvancedOptions = "spellDamageArcane"
                            Case AdvancedOptionsType.Spell_HolyDamage
                                strAdvancedOptions = "spellDamageHoly"
                            Case AdvancedOptionsType.Spell_ShadowDamage
                                strAdvancedOptions = "spellDamageShadow"
                            Case AdvancedOptionsType.Spell_NatureDamage
                                strAdvancedOptions = "spellDamageNature"
                            Case AdvancedOptionsType.Spell_FrostDamage
                                strAdvancedOptions = "spellDamageFrost"
                            Case AdvancedOptionsType.Spell_FireDamage
                                strAdvancedOptions = "spellDamageFire"
                            Case AdvancedOptionsType.Defense_Armor
                                strAdvancedOptions = "armor"
                            Case AdvancedOptionsType.Defense_BlockRating
                                strAdvancedOptions = "blockRating"
                            Case AdvancedOptionsType.Defense_DefenseRating
                                strAdvancedOptions = "defenseRating"
                            Case AdvancedOptionsType.Defense_DodgeRating
                                strAdvancedOptions = "dodgeRating"
                            Case AdvancedOptionsType.Defense_ParryRating
                                strAdvancedOptions = "parryRating"
                            Case AdvancedOptionsType.Defense_HealthRegen
                                strAdvancedOptions = "healthRegen"
                            Case AdvancedOptionsType.Defense_Resilience
                                strAdvancedOptions = "resilience"
                            Case AdvancedOptionsType.Resistance_ArcaneResist
                                strAdvancedOptions = "resistArcane"
                            Case AdvancedOptionsType.Resistance_ShadowResist
                                strAdvancedOptions = "resistShadow"
                            Case AdvancedOptionsType.Resistance_NatureResist
                                strAdvancedOptions = "resistNature"
                            Case AdvancedOptionsType.Resistance_FrostResist
                                strAdvancedOptions = "resistFrost"
                            Case AdvancedOptionsType.Resistance_FireResist
                                strAdvancedOptions = "resistFire"
                            Case AdvancedOptionsType.Weapon_Dps
                                strAdvancedOptions = "dps"
                            Case AdvancedOptionsType.Weapon_MinDamage
                                strAdvancedOptions = "minDamage"
                            Case AdvancedOptionsType.Weapon_MaxDamage
                                strAdvancedOptions = "maxDamage"
                            Case AdvancedOptionsType.Weapon_Speed
                                strAdvancedOptions = "speed"
                            Case AdvancedOptionsType.General_BindOnPickup
                                strAdvancedOptions = "bindsPickedUp"
                            Case AdvancedOptionsType.General_BindOnEquip
                                strAdvancedOptions = "bindsEquip"
                            Case AdvancedOptionsType.General_BindOnUse
                                strAdvancedOptions = "bindsWhenUsed"
                            Case AdvancedOptionsType.General_Unique
                                strAdvancedOptions = "unique"
                            Case AdvancedOptionsType.General_UniqueEquipped
                                strAdvancedOptions = "uniqueEquipped"
                            Case AdvancedOptionsType.General_SpellEffect_ChanceToResist
                                strAdvancedOptions = "hasSpellEffect_resist"
                            Case AdvancedOptionsType.General_SpellEffect_AvoidInterruption
                                strAdvancedOptions = "hasSpellEffect_interrupt"
                            Case AdvancedOptionsType.General_SpellEffect_ChanceOnHitOrCast
                                strAdvancedOptions = "hasSpellEffect_proc"
                            Case AdvancedOptionsType.General_SpellEffect_DispelEffects
                                strAdvancedOptions = "hasSpellEffect_dispel"
                            Case AdvancedOptionsType.General_SpellEffect_ReduceCooldown
                                strAdvancedOptions = "hasSpellEffect_cooldown"
                            Case AdvancedOptionsType.General_SpellEffect_ReduceCastTime
                                strAdvancedOptions = "hasSpellEffect_casttime"
                            Case AdvancedOptionsType.General_SpellEffect_ReduceSpellCost
                                strAdvancedOptions = "hasSpellEffect_spellcost"
                            Case AdvancedOptionsType.General_SpellEffect_IncreaseDuration
                                strAdvancedOptions = "hasSpellEffect_duration"
                            Case AdvancedOptionsType.General_SpellEffect_IncreaseRange
                                strAdvancedOptions = "hasSpellEffect_range"
                            Case AdvancedOptionsType.General_SpellEffect_ReduceThreat
                                strAdvancedOptions = "hasSpellEffect_threat"
                            Case AdvancedOptionsType.General_SpellEffect_GroupBuff
                                strAdvancedOptions = "hasSpellEffect_group"
                            Case AdvancedOptionsType.General_SpellEffect_SummonCreature
                                strAdvancedOptions = "hasSpellEffect_summon"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The type of operator to use with the advanced option filter
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property [Operator]() As AdvancedOptionsOperatorType
                    Get
                        Select Case strOperator
                            Case "gt"
                                Return AdvancedOptionsOperatorType.GreaterThan
                            Case "gteq"
                                Return AdvancedOptionsOperatorType.GreaterThanEqualTo
                            Case "eq"
                                Return AdvancedOptionsOperatorType.EqualTo
                            Case "lt"
                                Return AdvancedOptionsOperatorType.LessThan
                            Case "lteq"
                                Return AdvancedOptionsOperatorType.LessThanEqualTo
                            Case Else
                                Return Nothing
                        End Select
                    End Get
                    Set(ByVal value As AdvancedOptionsOperatorType)
                        If AdvancedOptions > AdvancedOptionsType.Weapon_Speed Then
                            Throw New InvalidOperationException("You cannot assign an operator to this option.")
                            Exit Property
                        End If
                        Select Case value
                            Case AdvancedOptionsOperatorType.GreaterThan
                                strOperator = "gt"
                            Case AdvancedOptionsOperatorType.GreaterThanEqualTo
                                strOperator = "gteq"
                            Case AdvancedOptionsOperatorType.EqualTo
                                strOperator = "eq"
                            Case AdvancedOptionsOperatorType.LessThan
                                strOperator = "lt"
                            Case AdvancedOptionsOperatorType.LessThanEqualTo
                                strOperator = "lteq"
                        End Select
                    End Set
                End Property

                ''' <summary>
                ''' The range to bue used with the operator for the advanced option filter
                ''' </summary>
                ''' <value></value>
                ''' <returns></returns>
                ''' <remarks></remarks>
                Public Property Range() As Integer
                    Get
                        Return intRange
                    End Get
                    Set(ByVal value As Integer)
                        If AdvancedOptions > AdvancedOptionsType.Weapon_Speed Then
                            Throw New InvalidOperationException("You cannot assign an operator to this option.")
                            Exit Property
                        End If
                        If value < 0 Then
                            Throw New ArgumentOutOfRangeException("Range", "The Range must be greater than or equal to zero.")
                            Exit Property
                        End If
                        intRange = value
                    End Set
                End Property

            End Class

        End Class

#End Region

    End Class

End Namespace
